package com.huhx.demo.lock;

import java.util.Collections;
import java.util.List;
import java.util.concurrent.CountDownLatch;

import org.I0Itec.zkclient.IZkDataListener;
import org.I0Itec.zkclient.ZkClient;

public class DistributedLock2 extends DistributedLock {
	
	private final String path = "/ordinal_lock";
	
	private String beforePath;
	private String currentPath;
	private CountDownLatch cdl = null;
	
	private final String hosts = "127.0.0.1:2181";
	
	protected ZkClient client;
	
	public DistributedLock2() {
		client = new ZkClient(hosts);
	}

	@Override
	protected void waitForLock() {
		IZkDataListener listener = new IZkDataListener() {
			public void handleDataDeleted(String dataPath) throws Exception {
				if (null != cdl) {
					cdl.countDown();
				}
			}
			
			public void handleDataChange(String dataPath, Object data) throws Exception {
				// TODO Auto-generated method stub
			}
		};
		client.subscribeDataChanges(beforePath, listener);
		//因为是高并发的情况，有可能上面的监听器还没创建完，就有客户端对节点进行操作
		if (client.exists(beforePath)) {
			cdl = new CountDownLatch(1);
			try {
				cdl.await();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		client.unsubscribeDataChanges(beforePath, listener);
	}

	@Override
	protected boolean tryLock() {
		if (null == currentPath || currentPath.length() <= 0) {
			currentPath = client.createEphemeralSequential(path + "/", "lock");
		}
		List<String> childrens = client.getChildren(path);
		Collections.sort(childrens);
		if (currentPath.equals(path + "/" + childrens.get(0))) {
			return true;
		} else {
			int index = Collections.binarySearch(childrens, currentPath.substring(6));
			beforePath = path + "/" + childrens.get(index - 1);
		}
		return false;
	}
}
